﻿using Kang.DbDoc.Interfaces;
using Kang.DbDoc.Models;
using Kang.ExtendMethod;
using NPOI.XWPF.Model;
using NPOI.XWPF.UserModel;
using NPOI.OpenXmlFormats.Wordprocessing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Kang.DbDoc.ServicesImpl
{
    public class WordExportService : IExport
    {
        public bool Export(string filename, DatabaseModel database, List<TableOrViewModel> tables, List<TableOrViewModel> views, List<RoutineModel> functions, List<RoutineModel> procedures, ref string error)
        {
            XWPFRun run = null;
            XWPFParagraph tableNameParagraph = null;
            XWPFParagraph tableCommentParagraph = null;
            XWPFTable table = null;
            XWPFTableCell cell = null;
            XWPFTableRow row = null;
            try
            {
                int m_i = 1;
                XWPFDocument document = new XWPFDocument();
                document.Document.body.AddNewSectPr();
                CT_SectPr sectPr = document.Document.body.sectPr;
                sectPr.pgNumType = new CT_PageNumber();
                CT_PageMar pageMar = sectPr.pgMar;
                pageMar.left = 720;
                pageMar.top = "720";
                pageMar.right = 720;
                pageMar.bottom = "720";
                pageMar.header = 460;
                pageMar.footer = 460;

                XWPFHeaderFooterPolicy headerFooterPolicy = document.CreateHeaderFooterPolicy();
                XWPFHeader header = headerFooterPolicy.CreateHeader(XWPFHeaderFooterPolicy.DEFAULT);
                XWPFParagraph paragraph = header.Paragraphs[0];
                paragraph.Alignment = ParagraphAlignment.RIGHT;
                run = paragraph.CreateRun();
                run.IsBold = true;
                run.FontSize = 12;
                run.FontFamily = "宋体";
                run.SetText("数据库字典文档");

                XWPFFooter footer = headerFooterPolicy.CreateFooter(XWPFHeaderFooterPolicy.DEFAULT);
                paragraph = footer.Paragraphs[0];
                paragraph.Alignment = ParagraphAlignment.CENTER;
                CT_P m_SdtContentP = paragraph.GetCTP();
                CT_SimpleField m_fldSimple = new CT_SimpleField();
                m_fldSimple.instr = " PAGE  \\* Arabic  \\* MERGEFORMAT ";
                m_SdtContentP.Items.Add(m_fldSimple);
                var m_SdtR = m_SdtContentP.AddNewR();
                m_SdtR.AddNewT().Value = " / ";
                m_fldSimple = new CT_SimpleField();
                m_fldSimple.instr = " NUMPAGES  \\* Arabic  \\* MERGEFORMAT ";
                m_SdtContentP.Items.Add(m_fldSimple);

                var documentTitleParagraph = document.CreateParagraph();
                documentTitleParagraph.Alignment = ParagraphAlignment.CENTER;
                run = documentTitleParagraph.CreateRun();
                run.IsBold = true;
                run.FontSize = 18;
                run.FontFamily = "宋体";
                if (database.DatabaseType == Enums.DatabaseTypeEnum.SQLite)
                {
                    run.SetText($"{Path.GetFileName(database.DatabaseName)}表结构文档");
                }
                else
                {
                    run.SetText($"{database.DatabaseName}表结构文档");
                }
                var databaseInfoParagraph = document.CreateParagraph();
                databaseInfoParagraph.setSpacingBetween(20, LineSpacingRule.EXACT);
                databaseInfoParagraph.Alignment = ParagraphAlignment.LEFT;
                run = databaseInfoParagraph.CreateRun();
                run.IsBold = true;
                run.FontSize = 14;
                run.FontFamily = "宋体";
                run.AppendText($"{GetChineseNum(m_i++)}、数据库信息");
                run.AddCarriageReturn();
                if (database.DatabaseType == Enums.DatabaseTypeEnum.SQLite)
                {
                    run.AppendText($"地址：{database.DatabaseName}");
                }
                else
                {
                    run.AppendText($"地址：{database.DatabaseHost}");
                }
                run.AddCarriageReturn();
                if (database.DatabasePort > 0)
                {
                    run.AppendText($"端口：{database.DatabasePort}");
                    run.AddCarriageReturn();
                }
                if(tables.Count > 0)
                {
                    run.AppendText($"表总数：{tables.Count}");
                    run.AddCarriageReturn();
                }
                if(views.Count > 0)
                {
                    run.AppendText($"视图总数：{views.Count}");
                    run.AddCarriageReturn();
                }
                if (functions.Count > 0)
                {
                    run.AppendText($"方法总数：{functions.Count}");
                    run.AddCarriageReturn();
                }
                if (procedures.Count > 0)
                {
                    run.AppendText($"存储过程总数：{procedures.Count}");
                    run.AddCarriageReturn();
                }
                run.AppendText($"{GetChineseNum(m_i++)}、修订日志");

                table = document.CreateTable(6, 5);
                table.Width = 5000; 
                row = table.GetRow(0);
                RenderWordTableTitleCell(ref row, 0, "版本号");
                RenderWordTableTitleCell(ref row, 1, "修订日期");
                RenderWordTableTitleCell(ref row, 2, "修订内容");
                RenderWordTableTitleCell(ref row, 3, "修订人");
                RenderWordTableTitleCell(ref row, 4, "审核人");

                var tableModelParagraph = document.CreateParagraph();
                run = tableModelParagraph.CreateRun();
                run.IsBold = true;
                run.FontSize = 18;
                run.FontFamily = "宋体";
                if (tables.Count > 0)
                {
                    run.AddBreak(BreakType.PAGE);
                    run.AppendText($"{GetChineseNum(m_i++)}、表信息");
                }
                int p_i = 0;
                foreach (var t in tables)
                {
                    tableNameParagraph = document.CreateParagraph();
                    tableNameParagraph.Alignment = ParagraphAlignment.CENTER;
                    run = tableNameParagraph.CreateRun();
                    run.FontFamily = "宋体";
                    run.IsBold = true;
                    if (p_i > 0)
                    {
                        run.AddBreak(BreakType.PAGE);
                    }
                    run.AppendText($"表：{t.Name}");

                    if (t.Comment.IsNotBlank())
                    {
                        tableCommentParagraph = document.CreateParagraph();
                        run = tableCommentParagraph.CreateRun();
                        run.FontFamily = "宋体";
                        run.AppendText($"注解：{t.Comment}");
                    }
                    table = document.CreateTable(1, 10);
                    table.Width = 5000;

                    row = table.GetRow(0);
                    RenderWordTableTitleCell(ref row, 0, "序号");
                    RenderWordTableTitleCell(ref row, 1, "列名");
                    RenderWordTableTitleCell(ref row, 2, "数据类型");
                    RenderWordTableTitleCell(ref row, 3, "长度");
                    RenderWordTableTitleCell(ref row, 4, "小数");
                    RenderWordTableTitleCell(ref row, 5, "键类型");
                    RenderWordTableTitleCell(ref row, 6, "自增");
                    RenderWordTableTitleCell(ref row, 7, "为空");
                    RenderWordTableTitleCell(ref row, 8, "默认");
                    RenderWordTableTitleCell(ref row, 9, "列说明");

                    int i = 1;
                    foreach (var c in t.Columns)
                    {
                        row = table.CreateRow();

                        RenderWordTableColumnCell(ref row, 0, $"{i++}");
                        RenderWordTableColumnCell(ref row, 1, $"{c.Name}");
                        RenderWordTableColumnCell(ref row, 2, $"{c.Type}");
                        RenderWordTableColumnCell(ref row, 3, $"{c.Length}");
                        RenderWordTableColumnCell(ref row, 4, $"{c.Scale}");
                        RenderWordTableColumnCell(ref row, 5, $"{c.KeyType}");
                        RenderWordTableColumnCell(ref row, 6, $"{(c.IsAutoIncrement ? "√" : "")}");
                        RenderWordTableColumnCell(ref row, 7, $"{(c.IsNull ? "√" : "")}");
                        RenderWordTableColumnCell(ref row, 8, $"{c.Default}");
                        RenderWordTableColumnCell(ref row, 9, $"{c.Comment}");
                    }
                    p_i++;
                }
                if (views.Count > 0)
                {
                    databaseInfoParagraph = document.CreateParagraph();
                    databaseInfoParagraph.setSpacingBetween(20, LineSpacingRule.EXACT);
                    run = databaseInfoParagraph.CreateRun();
                    run.IsBold = true;
                    run.FontSize = 14;
                    run.FontFamily = "宋体";
                    run.AddBreak(BreakType.PAGE);
                    run.AppendText($"{GetChineseNum(m_i++)}、视图信息");
                }
                p_i = 0;
                foreach (var v in views)
                {
                    tableNameParagraph = document.CreateParagraph();
                    tableNameParagraph.Alignment = ParagraphAlignment.CENTER;
                    run = tableNameParagraph.CreateRun();
                    run.FontFamily = "宋体";
                    run.IsBold = true;
                    if (p_i > 0)
                    {
                        run.AddBreak(BreakType.PAGE);
                    }
                    run.AppendText($"视图：{v.Name}");

                    if (v.Comment.IsNotBlank())
                    {
                        tableCommentParagraph = document.CreateParagraph();
                        run = tableCommentParagraph.CreateRun();
                        run.FontFamily = "宋体";
                        run.AppendText($"注解：{v.Comment}");
                    }
                    table = document.CreateTable(1, 10);
                    table.Width = 5000;

                    row = table.GetRow(0);
                    RenderWordTableTitleCell(ref row, 0, "序号");
                    RenderWordTableTitleCell(ref row, 1, "列名");
                    RenderWordTableTitleCell(ref row, 2, "数据类型");
                    RenderWordTableTitleCell(ref row, 3, "长度");
                    RenderWordTableTitleCell(ref row, 4, "小数");
                    RenderWordTableTitleCell(ref row, 5, "键类型");
                    RenderWordTableTitleCell(ref row, 6, "自增");
                    RenderWordTableTitleCell(ref row, 7, "为空");
                    RenderWordTableTitleCell(ref row, 8, "默认");
                    RenderWordTableTitleCell(ref row, 9, "列说明");

                    int i = 1;
                    foreach (var c in v.Columns)
                    {
                        row = table.CreateRow();

                        RenderWordTableColumnCell(ref row, 0, $"{i++}");
                        RenderWordTableColumnCell(ref row, 1, $"{c.Name}");
                        RenderWordTableColumnCell(ref row, 2, $"{c.Type}");
                        RenderWordTableColumnCell(ref row, 3, $"{c.Length}");
                        RenderWordTableColumnCell(ref row, 4, $"{c.Scale}");
                        RenderWordTableColumnCell(ref row, 5, $"{c.KeyType}");
                        RenderWordTableColumnCell(ref row, 6, $"{(c.IsAutoIncrement ? "√" : "")}");
                        RenderWordTableColumnCell(ref row, 7, $"{(c.IsNull ? "√" : "")}");
                        RenderWordTableColumnCell(ref row, 8, $"{c.Default}");
                        RenderWordTableColumnCell(ref row, 9, $"{c.Comment}");
                    }
                    p_i++;
                }
                if (functions.Count > 0)
                {
                    databaseInfoParagraph = document.CreateParagraph();
                    databaseInfoParagraph.setSpacingBetween(20, LineSpacingRule.EXACT);
                    run = databaseInfoParagraph.CreateRun();
                    run.IsBold = true;
                    run.FontSize = 14;
                    run.FontFamily = "宋体";
                    run.AddBreak(BreakType.PAGE);
                    run.AppendText($"{GetChineseNum(m_i++)}、方法信息");
                }
                p_i = 0;
                foreach (var f in functions)
                {
                    if (p_i > 0)
                    {
                        run.AddBreak(BreakType.PAGE);
                    }
                    table = document.CreateTable(4, 2);
                    table.Width = 5000;

                    row = table.GetRow(0);
                    RenderWordTableTitleCell(ref row, 0, "方法");
                    RenderWordTableColumnCell(ref row, 1, $"{f.Name}");

                    row = table.GetRow(1);
                    RenderWordTableTitleCell(ref row, 0, "注解");
                    RenderWordTableColumnCell(ref row, 1, $"{f.Comment}");

                    row = table.GetRow(2);
                    RenderWordTableTitleCell(ref row, 0, "创建者");
                    RenderWordTableColumnCell(ref row, 1, $"{f.Definer}");

                    row = table.GetRow(3);
                    row.MergeCells(0, 1);
                    RenderWordTableColumnCell(ref row, 0, $"{f.Definition}");
                    p_i++;
                }
                if (procedures.Count > 0)
                {
                    databaseInfoParagraph = document.CreateParagraph();
                    databaseInfoParagraph.setSpacingBetween(20, LineSpacingRule.EXACT);
                    run = databaseInfoParagraph.CreateRun();
                    run.IsBold = true;
                    run.FontSize = 14;
                    run.FontFamily = "宋体";
                    run.AddBreak(BreakType.PAGE);
                    run.AppendText($"{GetChineseNum(m_i++)}、存储过程信息");
                }
                p_i = 0;
                foreach (var p in procedures)
                {
                    if (p_i > 0)
                    {
                        run.AddBreak(BreakType.PAGE);
                    }
                    table = document.CreateTable(4, 2);
                    table.Width = 5000;

                    table.SetColumnWidth(0,90);

                    row = table.GetRow(0);
                    RenderWordTableTitleCell(ref row, 0, "存储过程");
                    RenderWordTableColumnCell(ref row, 1, $"{p.Name}");

                    row = table.GetRow(1);
                    RenderWordTableTitleCell(ref row, 0, "注解");
                    RenderWordTableColumnCell(ref row, 1, $"{p.Comment}");

                    row = table.GetRow(2);
                    RenderWordTableTitleCell(ref row, 0, "创建者");
                    RenderWordTableColumnCell(ref row, 1, $"{p.Definer}");

                    row = table.GetRow(3);
                    row.MergeCells(0, 1);
                    RenderWordTableColumnCell(ref row, 0, $"{p.Definition}");
                    p_i++;
                }

                using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
                {
                    document.Write(fs);
                }
                return true;
            }
            catch (Exception e)
            {
                error = e.Message;
                return false;
            }
        }

        public void RenderWordTableTitleCell(ref XWPFTableRow row, int index, string title)
        {
            var cell = row.GetCell(index);
            var c_p = cell.Paragraphs[0];
            var run = c_p.CreateRun();
            run.FontFamily = "宋体";
            run.SetText(title);
            run.IsBold = true;
        }

        public void RenderWordTableColumnCell(ref XWPFTableRow row, int index, string text)
        {
            var cell = row.GetCell(index);
            var c_p = cell.Paragraphs[0];
            var run = c_p.CreateRun();
            run.FontFamily = "宋体";
            var textList = text.Replace("\t", "    ").Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            int i = 0;
            textList.ForEach(x =>
            {
                if (i++ == 0)
                {
                    run.AppendText(x);
                }
                else
                {
                    c_p = cell.AddParagraph(); 
                    run = c_p.CreateRun();
                    run.AppendText(x);
                }
            });
        }

        public string GetChineseNum(int i)
        {
            switch (i)
            {
                case 0:
                    return "〇";
                case 1:
                    return "一";
                case 2:
                    return "二";
                case 3:
                    return "三";
                case 4:
                    return "四";
                case 5:
                    return "五";
                case 6:
                    return "六";
                case 7:
                    return "七";
                case 8:
                    return "八";
                case 9:
                    return "九";
                case 10:
                    return "十";
                case 11:
                    return "十一";
                case 12:
                    return "十二";
            }
            return string.Empty;
        }
    }
}
